/*
 * Copyright 2011 Mark Davidson.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.dctmcommons.impl;

import com.documentum.com.DfClientX;
import com.documentum.com.IDfClientX;
import com.documentum.fc.client.DfServiceException;
import com.documentum.fc.client.IDfClient;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSessionManager;
import com.documentum.fc.common.DfException;
import com.documentum.fc.common.DfLogger;
import com.documentum.fc.common.IDfLoginInfo;

import java.lang.Exception;
import java.lang.String;

import org.dctmcommons.DctmCommonsException;
import org.dctmcommons.IParamCheck;
import org.dctmcommons.ISessionCallback;
import org.dctmcommons.ISessionHelper;

/**
 * Session-related helper methods.
 */
public class SessionHelper implements ISessionHelper {

	/** The parameter check instance. */
	private static final IParamCheck paramCheck = ParamCheck.getInstance();

    /**
     * Default constructor.
     */
    private SessionHelper() {}

    /**
     * Factory method.
     * @return The session helper instance.
     */
    public static ISessionHelper getInstance() {
        return new SessionHelper();
    }

    /* (non-Javadoc)
	 * @see org.dctmcommons.impl.ISessionHelper#createSessionManager()
	 */
    @Override
	public IDfSessionManager createSessionManager() throws DfException {
        return createSessionManager(null, null, null, null);
    }

	/* (non-Javadoc)
	 * @see org.dctmcommons.impl.ISessionHelper#createSessionManager(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public IDfSessionManager createSessionManager(final String repository,
											      final String username,
											      final String password,
											      final String domain)
	    throws DfException {

        paramCheck.checkString(repository, "repository");
        paramCheck.checkString(username, "username");

		final IDfClientX clientx = new DfClientX();
		final IDfClient client = clientx.getLocalClient();
		final IDfSessionManager manager = client.newSessionManager();

        setIdentity(manager, repository, username, password, domain);

		return manager;
	}

    /* (non-Javadoc)
	 * @see org.dctmcommons.impl.ISessionHelper#setIdentity(com.documentum.fc.client.IDfSessionManager, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
    @Override
	public void setIdentity(final IDfSessionManager manager,
							final String repository,
                            final String username,
                            final String password,
                            final String domain) throws DfServiceException {

        paramCheck.checkObject(manager, "manager");
        paramCheck.checkString(repository, "repository");
        paramCheck.checkString(username, "username");

        final IDfLoginInfo loginInfo = createLoginInfo(username,
                                                       password,
                                                       domain);
        manager.setIdentity(repository, loginInfo);
    }

    /* (non-Javadoc)
	 * @see org.dctmcommons.impl.ISessionHelper#createLoginInfo(java.lang.String, java.lang.String, java.lang.String)
	 */
    @Override
	public IDfLoginInfo createLoginInfo(final String username,
                                        final String password,
                                        final String domain) {
        paramCheck.checkString(username, "username");

		final IDfClientX clientx = new DfClientX();
        final IDfLoginInfo loginInfo = clientx.getLoginInfo();
        loginInfo.setUser(username);
        loginInfo.setPassword(password);
        loginInfo.setDomain(domain);
        return loginInfo;
    }

    /* (non-Javadoc)
	 * @see org.dctmcommons.impl.ISessionHelper#impersonate(com.documentum.fc.client.IDfSession, java.lang.String)
	 */
    @Override
	public void impersonate(final IDfSession session, final String username)
        throws DfException {

        paramCheck.checkObject(session, "session");
        paramCheck.checkString(username, "username");

        final String ticket = session.getLoginTicketForUser(username);

        session.assume(createLoginInfo(username, ticket, null));
    }

    /* (non-Javadoc)
	 * @see org.dctmcommons.impl.ISessionHelper#releaseSession(com.documentum.fc.client.IDfSessionManager, com.documentum.fc.client.IDfSession)
	 */
    @Override
	public void releaseSession(final IDfSessionManager manager,
                               final IDfSession session) {
        if (manager != null && session != null) {
            manager.release(session);
        }
    }

    /* (non-Javadoc)
	 * @see org.dctmcommons.impl.ISessionHelper#releaseSession(com.documentum.fc.client.IDfSession)
	 */
    @Override
	public void releaseSession(final IDfSession session) {
        if (session != null) {
            session.getSessionManager().release(session);
        }
    }

    /* (non-Javadoc)
	 * @see org.dctmcommons.impl.ISessionHelper#useSession(java.lang.String, java.lang.String, java.lang.String, java.lang.String, boolean, org.dctmcommons.ISessionCallback)
	 */
    @Override
	public IDfSessionManager useSession(final String repository,
                                        final String username,
                                        final String password,
                                        final String domain,
                                        final boolean useTransaction,
                                        final ISessionCallback callback)
        throws DfException {

        paramCheck.checkString(repository, "repository");
        paramCheck.checkString(username, "username");

        final IDfSessionManager manager = createSessionManager(repository,
                                                               username,
                                                               password,
                                                               domain);
        useSession(manager, repository, useTransaction, callback);

        return manager;
    }

    /* (non-Javadoc)
	 * @see org.dctmcommons.impl.ISessionHelper#useSession(com.documentum.fc.client.IDfSessionManager, java.lang.String, boolean, org.dctmcommons.ISessionCallback)
	 */
    @Override
	public void useSession(final IDfSessionManager manager,
                           final String repository,
                           final boolean useTransaction,
                           final ISessionCallback callback) throws DfException {

        paramCheck.checkObject(manager, "manager");
        paramCheck.checkObject(repository, "repository");
        paramCheck.checkObject(callback, "callback");

        final IDfSession session = manager.getSession(repository);
        if (useTransaction) {
            session.beginTrans();
        }

        try {
            callback.useSession(session);

            if (useTransaction && session.isTransactionActive()) {
                session.commitTrans();
            }
        } catch (Exception e) {
            DfLogger.error(this, "Failure during session callback", null, e);

            if (useTransaction && session.isTransactionActive()) {
                session.abortTrans();
            }

            throw new DctmCommonsException(e);
        } finally {
            releaseSession(manager, session);
        }
    }
}
